<?php
declare(strict_types=1);

namespace ExpressionEngine\LoopEngine\Loop;

use Contract\Exceptions\LogicException;
use Contract\Exceptions\ValidationException;
use ExpressionEngine\ExpressionLogic;
use ExpressionEngine\LexicalAnalysisEngine\LexicalAnalysisTag;
use ExpressionEngine\LoopEngine\Enum\LoopEnum;
use ExpressionEngine\VariableEngine\VariableEngine;
use ExpressionEngine\VariableEngine\VariableEngineInterface;

class LoopForeach implements LoopInterface
{
    protected ExpressionLogic $expressionLogic;
    protected VariableEngine $variableEngine;
    protected LexicalAnalysisTag $lexicalAnalysisTag;

    public function __construct(ExpressionLogic $expressionLogic, VariableEngineInterface $variableEngine, LexicalAnalysisTag $lexicalAnalysisTag)
    {
        $this->expressionLogic = $expressionLogic;
        $this->variableEngine = $variableEngine;
        $this->lexicalAnalysisTag = $lexicalAnalysisTag;
    }


    /**
     * @param array $loopItem
     * @return bool
     */
    public function is(array $loopItem): bool
    {
        if ($loopItem[LoopEnum::LOOP_FOREACH_HEADER_NAME][LoopEnum::LOOP_FOREACH_HEADER_TYPE_NAME] == LoopEnum::LOOP_FOREACH_NAME) {
            return true;
        }
        return false;
    }

    /**
     * @param array $loopItem
     * @param array $context
     * @return mixed
     * @throws LogicException
     * @throws ValidationException
     */
    public function compile(array $loopItem, array $context): mixed
    {
        $listVariable = $loopItem[LoopEnum::LOOP_FOREACH_HEADER_NAME][LoopEnum::LOOP_FOREACH_HEADER_LIST_NAME];
        $listCompileValue = $this->variableEngine->compile($listVariable, $context, []);
        if (!is_array($listCompileValue)) {
            throw new LogicException('循环体list值不是数组 list:' . $listVariable);
        }

        $result = true;
        foreach ($listCompileValue as $key => $value) {
            $context = $this->mergeContext($context, [
                $loopItem[LoopEnum::LOOP_FOREACH_HEADER_NAME][LoopEnum::LOOP_FOREACH_HEADER_KEY_NAME] => $key,
                $loopItem[LoopEnum::LOOP_FOREACH_HEADER_NAME][LoopEnum::LOOP_FOREACH_HEADER_VALUE_NAME] => $value,
            ]);
            $result = $result && $this->expressionLogic->compile($loopItem, $context, []);
        }
        return $result;
    }

    /**
     * @param array $commonContext
     * @param array $currentContext
     * @return array
     */
    protected function mergeContext(array $commonContext, array $currentContext): array
    {
        return array_merge($commonContext, $currentContext);
    }
}